const PRODUIT = 0x04;
const CHARGE = 0x08;
- public function importPlan()
+ public function importPlan($file = NULL)
{
- $plan = json_decode(file_get_contents(ROOT . '/include/data/plan_comptable.json'), true);
+ $plan = json_decode(file_get_contents($file ? $file : ROOT.'/include/data/plan_comptable.json'), true);
$db = DB::getInstance();
$db->exec('BEGIN;');
}
}
- $db->exec('DELETE FROM compta_comptes WHERE id NOT IN(\''.implode('\', \'', $ids).'\') AND plan_comptable = 1;');
+ //$db->exec('DELETE FROM compta_comptes WHERE id NOT IN(\''.implode('\', \'', $ids).'\') AND plan_comptable = 1;');
$db->exec('END;');
$db = DB::getInstance();
// Ne pas supprimer un compte qui est utilisé !
- if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal WHERE compte_debit = ? OR compte_debit = ? LIMIT 1;', false, $id, $id))
+ if ($db->simpleQuerySingle('SELECT 1 FROM compta_flux WHERE compte = ? LIMIT 1;', false, $id))
{
throw new UserException('Ce compte ne peut être supprimé car des opérations comptables y sont liées.');
}
{
$db = DB::getInstance();
- if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
- WHERE compte_debit = ? OR compte_debit = ? LIMIT 1;', false, $id, $id))
+ if ($db->simpleQuerySingle('SELECT 1 FROM compta_flux
+ WHERE compte = ? LIMIT 1;', false, $id))
{
return false;
}
$db = DB::getInstance();
if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
- AND (compte_debit = ? OR compte_debit = ?) LIMIT 1;', false, $id, $id))
+ AND compte = ? LIMIT 1;', false, $id))
{
return false;
}
// Ne pas désactiver un compte utilisé dans l'exercice courant
if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
- AND (compte_debit = ? OR compte_debit = ?) LIMIT 1;', false, $id, $id))
+ AND compte = ? LIMIT 1;', false, $id))
{
throw new UserException('Ce compte ne peut être désactivé car des écritures y sont liées sur l\'exercice courant. '
. 'Il faut supprimer ou ré-attribuer ces écritures avant de pouvoir supprimer le compte.');
}
}
-?>
\ No newline at end of file
+?>
// Ne pas supprimer/désactiver un compte qui est utilisé dans l'exercice courant
if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
- AND (compte_debit = ? OR compte_debit = ?) LIMIT 1;', false, $id, $id))
+ AND compte = ? LIMIT 1;', false, $id))
{
throw new UserException('Ce compte ne peut être supprimé car des écritures y sont liées sur l\'exercice courant. '
. 'Il faut supprimer ou ré-attribuer ces écritures avant de pouvoir supprimer le compte.');
}
}
-?>
\ No newline at end of file
+?>
$journal->add([
'libelle' => 'Résultat de l\'exercice précédent',
'date' => $date,
- 'montant' => abs($resultat),
- 'compte_debit' => $resultat < 0 ? 129 : NULL,
- 'compte_credit' => $resultat > 0 ? 120 : NULL,
+ 'fluxs' =>
+ [ [ 'compte' => $resultat > 0 ? 129 : 120
+ , 'montant' => abs($resultat) ]
+ ]
]);
}
public function getJournal($exercice)
{
$db = DB::getInstance();
- $query = 'SELECT *, strftime(\'%s\', date) AS date FROM compta_journal
- WHERE id_exercice = '.(int)$exercice.' ORDER BY date, id;';
+ $query = 'SELECT *, strftime(\'%s\', date) AS date, -montant AS montant_oppose
+ FROM compta_flux
+ LEFT JOIN compta_journal ON compta_journal.id = compta_flux.id_journal
+ WHERE compta_journal.id_exercice = '.(int)$exercice.'
+ ORDER BY date, id;';
return $db->simpleStatementFetch($query);
}
$db = DB::getInstance();
$livre = ['classes' => [], 'debit' => 0.0, 'credit' => 0.0];
- $res = $db->prepare('SELECT compte FROM
- (SELECT compte_debit AS compte FROM compta_journal
- WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_debit
- UNION
- SELECT compte_credit AS compte FROM compta_journal
- WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_credit)
+ $res = $db->prepare('SELECT compte FROM compta_flux
+ LEFT JOIN compta_journal ON compta_journal.id = compta_flux.id_journal
+ WHERE id_exercice = '.(int)$exercice.'
ORDER BY base64(compte) COLLATE BINARY ASC;'
)->execute();
$livre['classes'][$classe][$parent]['comptes'][$compte] = ['debit' => 0.0, 'credit' => 0.0, 'journal' => []];
$livre['classes'][$classe][$parent]['comptes'][$compte]['journal'] = $db->simpleStatementFetch(
- 'SELECT *, strftime(\'%s\', date) AS date FROM (
- SELECT * FROM compta_journal WHERE compte_debit = :compte AND id_exercice = '.(int)$exercice.'
- UNION
- SELECT * FROM compta_journal WHERE compte_credit = :compte AND id_exercice = '.(int)$exercice.'
- )
- ORDER BY date, numero_piece, id;', SQLITE3_ASSOC, ['compte' => $compte]);
+ 'SELECT *, strftime(\'%s\', date) AS date FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE compte = :compte AND id_exercice = '.(int)$exercice.'
+ ORDER BY date, numero_piece, id;', SQLITE3_ASSOC, ['compte' => $compte]);
$debit = (float) $db->simpleQuerySingle(
- 'SELECT SUM(montant) FROM compta_journal WHERE compte_debit = ? AND id_exercice = '.(int)$exercice.';',
+ 'SELECT SUM(montant) FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE compte = ? AND montant > 0 AND id_exercice = '.(int)$exercice.';',
false, $compte);
-
$credit = (float) $db->simpleQuerySingle(
- 'SELECT SUM(montant) FROM compta_journal WHERE compte_credit = ? AND id_exercice = '.(int)$exercice.';',
+ 'SELECT -SUM(montant) FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE compte = ? AND montant < 0 AND id_exercice = '.(int)$exercice.';',
false, $compte);
$livre['classes'][$classe][$parent]['comptes'][$compte]['debit'] = $debit;
$res = $db->prepare('SELECT compte, SUM(debit), SUM(credit)
FROM
- (SELECT compte_debit AS compte, SUM(montant) AS debit, 0 AS credit
- FROM compta_journal WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_debit
+ (SELECT compte, SUM(montant) AS debit, 0 AS credit
+ FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE montant > 0 AND id_exercice = '.(int)$exercice.' GROUP BY compte
UNION
- SELECT compte_credit AS compte, 0 AS debit, SUM(montant) AS credit
- FROM compta_journal WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_credit)
+ SELECT compte, 0 AS debit, -SUM(montant) AS credit
+ FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE montant < 0 AND id_exercice = '.(int)$exercice.' GROUP BY compte)
WHERE compte LIKE \'6%\' OR compte LIKE \'7%\'
GROUP BY compte
ORDER BY base64(compte) COLLATE BINARY ASC;'
)->execute();
+
while ($row = $res->fetchArray(SQLITE3_NUM))
{
list($compte, $debit, $credit) = $row;
+ print_r([$compte, $debit, $credit]);
$classe = substr($compte, 0, 1);
$parent = substr($compte, 0, 2);
// soit fait au niveau du SQL, mais pour le moment ça marche
$res = $db->prepare('SELECT compte, debit, credit, (SELECT position FROM compta_comptes WHERE id = compte) AS position
FROM
- (SELECT compte_debit AS compte, SUM(montant) AS debit, NULL AS credit
- FROM compta_journal WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_debit
+ (SELECT compte, SUM(montant) AS debit, NULL AS credit
+ FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE montant > 0 AND id_exercice = '.(int)$exercice.' GROUP BY compte
UNION
- SELECT compte_credit AS compte, NULL AS debit, SUM(montant) AS credit
- FROM compta_journal WHERE id_exercice = '.(int)$exercice.' GROUP BY compte_credit)
+ SELECT compte, NULL AS debit, SUM(montant) AS credit
+ FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE montant < 0 AND id_exercice = '.(int)$exercice.' GROUP BY compte)
WHERE compte IN (SELECT id FROM compta_comptes WHERE position IN ('.implode(', ', $include).'))
ORDER BY base64(compte) COLLATE BINARY ASC;'
)->execute();
}
}
-?>
\ No newline at end of file
+?>
{
$db = DB::getInstance();
- $res = $db->prepare('SELECT
- journal.id,
- strftime(\'%d/%m/%Y\', date) AS date,
- (CASE cat.type WHEN 1 THEN \'Recette\' WHEN -1 THEN \'Dépense\' ELSE \'Autre\' END) AS type,
- (CASE cat.intitule WHEN NULL THEN \'\' ELSE cat.intitule END) AS cat,
- journal.libelle,
- montant,
- compte_debit,
- debit.libelle AS libelle_debit,
- compte_credit,
- credit.libelle AS libelle_credit,
- (CASE moyen_paiement WHEN NULL THEN \'\' ELSE moyen.nom END) AS moyen,
- numero_cheque,
- numero_piece,
- remarques
+ $retro_comptatibility = 'SELECT count(montant) AS montants FROM compta_flux WHERE compta_flux.id_journal = journal.id';
+ $res = $db->prepare('
+ SELECT
+ journal.id,
+ strftime(\'%d/%m/%Y\', date) AS date,
+ (CASE cat.type WHEN 1 THEN \'Recette\' WHEN -1 THEN \'Dépense\' ELSE \'Autre\' END) AS type,
+ (CASE cat.intitule WHEN NULL THEN \'\' ELSE cat.intitule END),
+ journal.libelle,
+ abs(flux.montant) AS montant,
+ (CASE WHEN flux.montant >= 0 THEN flux.compte ELSE \'\' END),
+ (CASE WHEN flux.montant >= 0 THEN flux_compte.libelle ELSE \'\' END) AS compte_debit_libelle,
+ (CASE WHEN flux.montant < 0 THEN flux.compte ELSE \'\' END),
+ (CASE WHEN flux.montant < 0 THEN flux_compte.libelle ELSE \'\' END) AS compte_credit_libelle,
+ (CASE moyen_paiement WHEN NULL THEN \'\' ELSE moyen.nom END) AS moyen,
+ numero_cheque,
+ numero_piece,
+ remarques
FROM compta_journal AS journal
LEFT JOIN compta_categories AS cat ON cat.id = journal.id_categorie
- LEFT JOIN compta_comptes AS debit ON debit.id = journal.compte_debit
- LEFT JOIN compta_comptes AS credit ON credit.id = journal.compte_credit
LEFT JOIN compta_moyens_paiement AS moyen ON moyen.code = journal.moyen_paiement
+ LEFT JOIN compta_flux AS flux ON flux.id_journal = journal.id
+ LEFT JOIN compta_comptes AS flux_compte ON flux_compte.id = flux.compte
WHERE id_exercice = '.(int)$exercice.'
- ORDER BY journal.date;
+ ORDER BY journal.id;
')->execute();
$fp = fopen('php://output', 'w');
};
$line = 0;
+ $last_id = 0;
+ $id = 0;
$delim = utils::find_csv_delim($fp);
+ unset($data);
while (!feof($fp))
{
$row = fgetcsv($fp, 4096, $delim);
+ print_r(["row" => $row]);
$line++;
if (empty($row))
throw new UserException('Erreur sur la ligne ' . $line . ' : la première colonne doit être vide ou contenir le numéro unique d\'opération.');
}
+ $last_id = $id;
$id = $col('Numéro mouvement');
- $date = $col('Date');
-
- if (!preg_match('!^\d{2}/\d{2}/\d{4}$!', $date))
+ if ($id == $last_id)
{
- $db->exec('ROLLBACK;');
- throw new UserException('Erreur sur la ligne ' . $line . ' : la date n\'est pas au format jj/mm/aaaa.');
+ $montant = $col('Montant');
+ $debit = $col('Compte de débit - numéro');
+ $credit = $col('Compte de crédit - numéro');
+
+ if (trim($debit) == '' && trim($credit) != '')
+ {
+ $debit = null;
+ $fluxs[] =
+ [ 'compte' => $credit
+ , 'montant' => - $montant
+ ];
+ }
+ if (trim($debit) != '' && trim($credit) == '')
+ {
+ $credit = null;
+ $fluxs[] =
+ [ 'compte' => $debit
+ , 'montant' => $montant
+ ];
+ }
}
+ else
+ {
+ if (isset($data)) {
+ // NOTE: import previously collected $last_id
+ $data['fluxs'] = $fluxs;
+ $id_journal = $db->simpleQuerySingle('SELECT id FROM compta_journal WHERE id = ?;', false, $last_id);
+ if (empty($last_id) || empty($id_journal))
+ {
+ print_r(["data" => $data]);
+ $journal->add($data);
+ }
+ else
+ {
+ print_r(['id' => $last_id, "data" => $data]);
+ $journal->edit($last_id, $data);
+ }
+ unset($data);
+ }
+
+ // NOTE: start collecting $id
+ $fluxs = [];
+ $date = $col('Date');
+
+ if (!preg_match('!^\d{2}/\d{2}/\d{4}$!', $date))
+ {
+ $db->exec('ROLLBACK;');
+ throw new UserException('Erreur sur la ligne ' . $line . ' : la date n\'est pas au format jj/mm/aaaa.');
+ }
- $date = explode('/', $date);
- $date = $date[2] . '-' . $date[1] . '-' . $date[0];
+ $date = explode('/', $date);
+ $date = $date[2] . '-' . $date[1] . '-' . $date[0];
- // En dehors de l'exercice courant
- if ($db->simpleQuerySingle('SELECT 1 FROM compta_exercices
- WHERE (? < debut OR ? > fin) AND cloture = 0;', false, $date, $date))
- {
- continue;
- }
+ // En dehors de l'exercice courant
+ if ($db->simpleQuerySingle('SELECT 1 FROM compta_exercices
+ WHERE (? < debut OR ? > fin) AND cloture = 0;', false, $date, $date))
+ {
+ continue;
+ }
- $debit = $col('Compte de débit - numéro');
- $credit = $col('Compte de crédit - numéro');
+ $cat = $col('Catégorie');
+ $moyen = strtoupper(substr($col('Moyen de paiement'), 0, 2));
- if (trim($debit) == '' && trim($credit) != '')
- {
- $debit = null;
- }
- elseif (trim($debit) != '' && trim($credit) == '')
- {
- $credit = null;
- }
+ if (!$moyen || !array_key_exists($moyen, $liste_moyens))
+ {
+ $moyen = false;
+ $cat = false;
+ }
- $cat = $col('Catégorie');
- $moyen = strtoupper(substr($col('Moyen de paiement'), 0, 2));
+ if ($cat && !array_key_exists($cat, $liste_cats))
+ {
+ $cat = $moyen = false;
+ }
- if (!$moyen || !array_key_exists($moyen, $liste_moyens))
- {
- $moyen = false;
- $cat = false;
- }
+ $montant = $col('Montant');
+ $debit = $col('Compte de débit - numéro');
+ $credit = $col('Compte de crédit - numéro');
- if ($cat && !array_key_exists($cat, $liste_cats))
- {
- $cat = $moyen = false;
- }
+ if (trim($debit) == '' && trim($credit) != '')
+ {
+ $debit = null;
+ $fluxs[] =
+ [ 'compte' => $credit
+ , 'montant' => - $montant
+ ];
+ }
+ if (trim($debit) != '' && trim($credit) == '')
+ {
+ $credit = null;
+ $fluxs[] =
+ [ 'compte' => $debit
+ , 'montant' => $montant
+ ];
+ }
- $data = [
- 'libelle' => $col('Libellé'),
- 'montant' => (float) $col('Montant'),
- 'date' => $date,
- 'compte_credit' => $credit,
- 'compte_debit' => $debit,
- 'numero_piece' => $col('Numéro de pièce'),
- 'remarques' => $col('Remarques'),
- ];
+ $data = [
+ 'libelle' => $col('Libellé'),
+ 'date' => $date,
+ 'numero_piece' => $col('Numéro de pièce'),
+ 'remarques' => $col('Remarques'),
+ ];
- if ($cat)
- {
- $data['moyen_paiement'] = $moyen;
- $data['numero_cheque'] = $col('Numéro de chèque');
- $data['id_categorie'] = $liste_cats[$cat];
+ if ($cat)
+ {
+ $data['moyen_paiement'] = $moyen;
+ $data['numero_cheque'] = $col('Numéro de chèque');
+ $data['id_categorie'] = $liste_cats[$cat];
+ }
}
-
- if (empty($id))
+ }
+ if (isset($data)) {
+ // NOTE: import previously collected $id
+ $data['fluxs'] = $fluxs;
+ $id_journal = $db->simpleQuerySingle('SELECT id FROM compta_journal WHERE id = ?;', false, $id);
+ if (empty($id) || empty($id_journal))
{
+ print_r(["data" => $data]);
$journal->add($data);
}
else
{
+ print_r(['id (end)' => $id, "data" => $data]);
$journal->edit($id, $data);
}
- }
+ unset($data);
+ }
$db->exec('END;');
}
}
-?>
\ No newline at end of file
+?>
? 'LIKE \'' . $db->escapeString(trim($id_compte)) . '%\''
: '= \'' . $db->escapeString(trim($id_compte)) . '\'';
- $debit = 'COALESCE((SELECT SUM(montant) FROM compta_journal WHERE compte_debit '.$compte.' AND id_exercice = '.(int)$exercice.'), 0)';
- $credit = 'COALESCE((SELECT SUM(montant) FROM compta_journal WHERE compte_credit '.$compte.' AND id_exercice = '.(int)$exercice.'), 0)';
+ $solde = 'COALESCE((SELECT SUM(montant) FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE compte '.$compte.' AND id_exercice = '.(int)$exercice.'), 0)';
- // L'actif augmente au débit, le passif au crédit
- $position = $db->simpleQuerySingle('SELECT position FROM compta_comptes WHERE id = ?;', false, $id_compte);
-
- if (($position & Compta_Comptes::ACTIF) || ($position & Compta_Comptes::CHARGE))
- {
- $query = $debit . ' - ' . $credit;
- }
- else
- {
- $query = $credit . ' - ' . $debit;
- }
-
- return $db->querySingle('SELECT ' . $query . ';');
+ return $db->querySingle('SELECT ' . $solde . ';');
}
public function getJournalCompte($compte, $inclure_sous_comptes = false)
{
$db = DB::getInstance();
- $position = $db->simpleQuerySingle('SELECT position FROM compta_comptes WHERE id = ?;', false, $compte);
-
$exercice = $this->_getCurrentExercice();
$compte = $inclure_sous_comptes
? 'LIKE \'' . $db->escapeString(trim($compte)) . '%\''
: '= \'' . $db->escapeString(trim($compte)) . '\'';
- // L'actif et les charges augmentent au débit, le passif et les produits au crédit
- if (($position & Compta_Comptes::ACTIF) || ($position & Compta_Comptes::CHARGE))
- {
- $d = '';
- $c = '-';
- }
- else
- {
- $d = '-';
- $c = '';
- }
-
- $query = 'SELECT *, strftime(\'%s\', date) AS date,
- running_sum(CASE WHEN compte_debit '.$compte.' THEN '.$d.'montant ELSE '.$c.'montant END) AS solde
- FROM compta_journal WHERE (compte_debit '.$compte.' OR compte_credit '.$compte.') AND id_exercice = '.(int)$exercice.'
+ $query = 'SELECT *, strftime(\'%s\', date) AS date, running_sum(compta_flux.montant) AS solde
+ FROM compta_flux
+ LEFT JOIN compta_journal ON compta_journal.id = compta_flux.id_journal
+ WHERE compta_flux.compte '.$compte.' AND compta_journal.id_exercice = '.(int)$exercice.'
ORDER BY date ASC;';
// Obligatoire pour bien taper dans l'index de la date
$data['id_exercice'] = $this->_getCurrentExercice();
+ $fluxs = $data['fluxs'];
+ unset($data['fluxs']);
+
$db->simpleInsert('compta_journal', $data);
$id = $db->lastInsertRowId();
+ foreach ($fluxs as $flux)
+ {
+ $db->simpleInsert('compta_flux', $flux + ['id_journal' => $id]);
+ }
+ $data['fluxs'] = $fluxs;
+
return $id;
}
$this->_checkFields($data);
- $db->simpleUpdate('compta_journal', $data,
- 'id = \''.trim($id).'\'');
+ $fluxs = $data['fluxs'];
+ unset($data['fluxs']);
+
+ $db->simpleUpdate('compta_journal', $data, 'id = \''.trim($id).'\'');
+
+ $db->simpleExec('DELETE FROM compta_flux WHERE id_journal = ?;', (int)$id);
+ foreach ($fluxs as $flux)
+ {
+ $db->simpleInsert('compta_flux', $flux + ['id_journal' => (int)$id]);
+ }
+ $data['fluxs'] = $fluxs;
return true;
}
public function get($id)
{
$db = DB::getInstance();
- return $db->simpleQuerySingle('SELECT *, strftime(\'%s\', date) AS date FROM compta_journal WHERE id = ?;', true, $id);
+ $journal = $db->simpleQuerySingle('SELECT *, strftime(\'%s\', date) AS date FROM compta_journal WHERE id = ?;', true, $id);
+ $fluxs = $db->simpleStatementFetch('SELECT * FROM compta_flux WHERE id_journal = ?
+ ORDER BY base64(compte) COLLATE BINARY ASC;', true, $id);
+ return ($journal + ['fluxs' => $fluxs]);
}
public function countForMember($id)
public function listForMember($id, $exercice)
{
$db = DB::getInstance();
- return $db->simpleStatementFetch('SELECT * FROM compta_journal
+ $journal = $db->simpleStatementFetch('SELECT * FROM compta_journal
WHERE id_auteur = ? AND id_exercice = ?;', \SQLITE3_ASSOC, (int)$id, (int)$exercice);
+ $fluxs = $db->simpleStatementFetch('SELECT * FROM compta_flux WHERE id_journal = ?
+ ORDER BY base64(compte) COLLATE BINARY ASC;', true, $journal['id']);
+ return ($journal + ['fluxs' => $fluxs]);
}
protected function _checkFields(&$data)
}
}
- $data['montant'] = str_replace(',', '.', $data['montant']);
- $data['montant'] = (float)$data['montant'];
-
- if ($data['montant'] <= 0)
- {
- throw new UserException('Le montant ne peut être égal ou inférieur à zéro.');
- }
foreach (['remarques', 'numero_piece', 'numero_cheque'] as $champ)
{
}
}
- if (!array_key_exists('compte_debit', $data) ||
- (!is_null($data['compte_debit']) &&
- !$db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $data['compte_debit'])))
+ $sum_montant = 0;
+ foreach ($data['fluxs'] as $flux)
{
- throw new UserException('Compte débité inconnu.');
+ if (!array_key_exists('compte', $flux) ||
+ (!is_null($flux['compte']) &&
+ !$db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $flux['compte'])))
+ {
+ throw new UserException('Compte débité inconnu.');
+ }
+ $flux['compte'] = is_null($flux['compte']) ? null : strtoupper(trim($flux['compte']));
+
+ $flux['montant'] = str_replace(',', '.', $flux['montant']);
+ $flux['montant'] = (float)$flux['montant'];
+
+ $sum_montant = round($sum_montant + $flux['montant'], 2);
}
- if (!array_key_exists('compte_credit', $data) ||
- (!is_null($data['compte_credit']) &&
- !$db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $data['compte_credit'])))
- {
- throw new UserException('Compte crédité inconnu.');
- }
-
- $data['compte_credit'] = is_null($data['compte_credit']) ? null : strtoupper(trim($data['compte_credit']));
- $data['compte_debit'] = is_null($data['compte_debit']) ? null : strtoupper(trim($data['compte_debit']));
-
- if ($data['compte_credit'] == $data['compte_debit'])
+ if ($sum_montant != 0)
{
- throw new UserException('Compte crédité identique au compte débité.');
+ throw new UserException('Somme non-nulle des montants des flux: '.print_r($data, true));
}
if (isset($data['id_categorie']))
}
}
-?>
\ No newline at end of file
+?>
{
return $this->getStats('SELECT strftime(\'%Y%m\', date) AS date,
SUM(montant) FROM compta_journal
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
WHERE id_categorie IN (SELECT id FROM compta_categories WHERE type = '.$type.')
AND id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0)
GROUP BY strftime(\'%Y-%m\', date) ORDER BY date;');
return $this->_parType(Compta_Categories::DEPENSES);
}
- public function soldeCompte($compte, $augmente = 'debit', $diminue = 'credit')
+ public function soldeCompte($compte)
{
$db = DB::getInstance();
$stats = $this->getStats('SELECT strftime(\'%Y%m\', date) AS date,
(COALESCE((SELECT SUM(montant) FROM compta_journal
- WHERE compte_'.$augmente.' '.$compte.' AND id_exercice = cj.id_exercice
- AND date >= strftime(\'%Y-%m-01\', cj.date)
- AND date <= strftime(\'%Y-%m-31\', cj.date)), 0)
- - COALESCE((SELECT SUM(montant) FROM compta_journal
- WHERE compte_'.$diminue.' '.$compte.' AND id_exercice = cj.id_exercice
+ LEFT JOIN compta_flux ON compta_journal.id = compta_flux.id_journal
+ WHERE compte '.$compte.' AND id_exercice = cj.id_exercice
AND date >= strftime(\'%Y-%m-01\', cj.date)
AND date <= strftime(\'%Y-%m-31\', cj.date)), 0)
) AS solde
FROM compta_journal AS cj
- WHERE (compte_debit '.$compte.' OR compte_credit '.$compte.')
+ WHERE (compte '.$compte.')
AND id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0)
GROUP BY strftime(\'%Y-%m\', date) ORDER BY date;');
}
}
-?>
\ No newline at end of file
+?>
$id_operation = $journal->add([
'libelle' => $data['libelle'],
- 'montant' => $data['montant'],
'date' => $data['date'],
+ 'fluxs' =>
+ [ ['compte'=>$credit, 'montant' => - $data['montant'] ]
+ , ['compte'=>$debit, 'montant' => $data['montant'] ] ],
'moyen_paiement'=> $data['moyen_paiement'],
'numero_cheque' => isset($data['numero_cheque']) ? $data['numero_cheque'] : null,
- 'compte_debit' => $debit,
- 'compte_credit' => $credit,
'id_categorie' => (int)$data['id_categorie'],
'id_auteur' => (int)$data['id_auteur'],
]);
return $db->simpleQuerySingle('SELECT COUNT(DISTINCT id_cotisation) FROM cotisations_membres
WHERE id_membre = ?;', false, (int)$id);
}
-}
\ No newline at end of file
+}
public function simpleStatement($query, $args = [])
{
+ //print_r(['query' => $query, 'args' => $args]);
$statement = $this->prepare($query);
$nb = $statement->paramCount();
}
}
-?>
\ No newline at end of file
+?>
}
}
-?>
\ No newline at end of file
+?>
remarques TEXT,
numero_piece TEXT, -- N° de pièce comptable
- montant REAL,
-
date TEXT DEFAULT CURRENT_DATE,
moyen_paiement TEXT DEFAULT NULL,
numero_cheque TEXT DEFAULT NULL,
- compte_debit TEXT, -- N° du compte dans le plan
- compte_credit TEXT, -- N° du compte dans le plan
-
id_exercice INTEGER NULL DEFAULT NULL, -- En cas de compta simple, l'exercice est permanent (NULL)
id_auteur INTEGER NULL,
id_categorie INTEGER NULL, -- Numéro de catégorie (en mode simple)
FOREIGN KEY(moyen_paiement) REFERENCES compta_moyens_paiement(code),
- FOREIGN KEY(compte_debit) REFERENCES compta_comptes(id),
- FOREIGN KEY(compte_credit) REFERENCES compta_comptes(id),
FOREIGN KEY(id_exercice) REFERENCES compta_exercices(id),
FOREIGN KEY(id_auteur) REFERENCES membres(id),
FOREIGN KEY(id_categorie) REFERENCES compta_categories(id)
);
+CREATE TABLE compta_flux
+(
+ id_journal INTEGER,
+
+ compte TEXT, -- N° du compte dans le plan
+ montant REAL,
+
+ FOREIGN KEY(id_journal) REFERENCES compta_journal(id) ON DELETE CASCADE,
+ FOREIGN KEY(compte) REFERENCES compta_comptes(id) ON DELETE CASCADE
+);
+
CREATE INDEX compta_operations_exercice ON compta_journal (id_exercice);
CREATE INDEX compta_operations_date ON compta_journal (date);
-CREATE INDEX compta_operations_comptes ON compta_journal (compte_debit, compte_credit);
+--CREATE INDEX compta_operations_comptes ON compta_journal (compte_debit, compte_credit);
CREATE INDEX compta_operations_auteur ON compta_journal (id_auteur);
CREATE TABLE compta_moyens_paiement
version TEXT NOT NULL,
menu INTEGER NOT NULL DEFAULT 0,
config TEXT
-);
\ No newline at end of file
+);
$name = $params['name'];
$comptes = $params['comptes'];
$selected = isset($params['data'][$params['name']]) ? $params['data'][$params['name']] : utils::post($name);
+ $id = isset($params['id']) ? $params['id'] : "f_$name";
+ $form_name = isset($params['form_name']) ? $params['form_name'] : $name;
- $out = '<select name="'.$name.'" id="f_'.$name.'" class="large">';
+ $out = '<select name="'.$form_name.'" id="'.$id.'" class="large">';
foreach ($comptes as $compte)
{
$tpl->register_modifier('strftime_fr', 'Garradin\tpl_strftime_fr');
$tpl->register_modifier('date_fr', 'Garradin\tpl_date_fr');
-?>
\ No newline at end of file
+?>
</colgroup>
<thead>
<tr>
- <td></td>
- <td></td>
- <td>Date</td>
- <td>Montant</td>
- <td>Solde cumulé</td>
+ <th></th>
+ <th></th>
+ <th>Date</th>
+ <th>Montant</th>
+ <th>Solde cumulé</th>
<th>Libellé</th>
</tr>
</thead>
{/if}
</td>
<td>{$ligne.date|date_fr:'d/m/Y'|escape}</td>
- <td>{if $ligne.compte_credit == $compte.id}{$credit}{else}{$debit}{/if}{$ligne.montant|html_money}</td>
+ <td>{$ligne.montant|html_money}</td>
<td>{$ligne.solde|html_money}</td>
- <th>{$ligne.libelle|escape}</th>
+ <td>{$ligne.libelle|escape}</td>
</tr>
{/foreach}
</tbody>
</tfoot>
</table>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
<tbody>
{foreach from=$bilan.actif.comptes key="parent_code" item="parent"}
<tr class="parent">
- <th>{$parent_code|get_nom_compte|escape}</th>
+ <th><span class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$parent_code|escape}">{$parent_code|escape}</a> — {$parent_code|get_nom_compte|escape}</th>
<td>{$parent.solde|html_money}</td>
</tr>
{foreach from=$parent.comptes item="solde" key="compte"}
<tr class="compte">
- <th>{$compte|get_nom_compte|escape}</th>
+ <th><span class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$compte|escape}">{$compte|escape}</a> — {$compte|get_nom_compte|escape}</th>
<td>{$solde|html_money}</td>
</tr>
{/foreach}
<tbody>
{foreach from=$bilan.passif.comptes key="parent_code" item="parent"}
<tr class="parent">
- <th>{$parent_code|get_nom_compte|escape}</th>
+ <th><span class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$parent_code|escape}">{$parent_code|escape}</a></span> — {$parent_code|get_nom_compte|escape}</th>
<td>{$parent.solde|html_money}</td>
</tr>
{foreach from=$parent.comptes item="solde" key="compte"}
<tr class="compte">
- <th>{$compte|get_nom_compte|escape}</th>
+ <th><span class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$compte|escape}">{$compte|escape}</a></span> — {$compte|get_nom_compte|escape}</th>
<td>{$solde|html_money}</td>
</tr>
{/foreach}
<p class="help">Toutes les opérations sont libellées en {$config.monnaie|escape}.</p>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
<tbody>
{foreach from=$compte_resultat.charges.comptes key="parent_code" item="parent"}
<tr class="parent">
- <th>{$parent_code|get_nom_compte|escape}</th>
+ <th>{$parent_code} — {$parent_code|get_nom_compte|escape}</th>
<td>{$parent.solde|html_money}</td>
</tr>
{foreach from=$parent.comptes item="solde" key="compte"}
<tr class="compte">
- <th>{$compte|get_nom_compte|escape}</th>
+ <th>{$compte|escape} — {$compte|get_nom_compte|escape}</th>
<td>{$solde|html_money}</td>
</tr>
{/foreach}
<tbody>
{foreach from=$compte_resultat.produits.comptes key="parent_code" item="parent"}
<tr class="parent">
- <th>{$parent_code|get_nom_compte|escape}</th>
+ <th>{$parent_code} — {$parent_code|get_nom_compte|escape}</th>
<td>{$parent.solde|html_money}</td>
</tr>
{foreach from=$parent.comptes item="solde" key="compte"}
<tr class="compte">
- <th>{$compte|get_nom_compte|escape}</th>
+ <th>{$compte|escape} — {$compte|get_nom_compte|escape}</th>
<td>{$solde|html_money}</td>
</tr>
{/foreach}
<p class="help">Toutes les opérations sont libellées en {$config.monnaie|escape}.</p>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
{foreach from=$comptes item="compte" key="code"}
{foreach from=$compte.comptes item="souscompte" key="souscode"}
<table class="list">
- <caption><h4>{$souscode|escape} — {$souscode|get_nom_compte|escape}</h4></caption>
+ <caption><h4 class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$souscode|escape}">{$souscode|escape}</a> — {$souscode|get_nom_compte|escape}</h4></caption>
<colgroup>
- <col width="15%" />
+ <col width="5%" />
+ <col width="10%" />
<col width="65%" />
<col width="10%" />
<col width="10%" />
</colgroup>
<thead>
<tr>
- <td>Date</td>
+ <th>N°</th>
+ <th>Date</th>
<th>Intitulé</th>
- <td>Débit</td>
- <td>Crédit</td>
+ <th>Débit</th>
+ <th>Crédit</th>
</tr>
</thead>
<tbody>
{foreach from=$souscompte.journal item="ligne"}
<tr>
+ <td class="num"><a href="{$admin_url}compta/operations/voir.php?id={$ligne.id|escape}">{$ligne.id|escape}</a></td>
<td>{$ligne.date|date_fr:'d/m/Y'|escape}</td>
<th>{$ligne.libelle|escape}</th>
- <td>{if $ligne.compte_debit == $souscode}{$ligne.montant|html_money}{/if}</td>
- <td>{if $ligne.compte_credit == $souscode}{$ligne.montant|html_money}{/if}</td>
+ <td>{if $ligne.compte == $souscode && $ligne.montant > 0}{$ligne.montant|html_money}{/if}</td>
+ <td>{if $ligne.compte == $souscode && $ligne.montant < 0}{$ligne.montant|abs|html_money}{/if}</td>
</tr>
{/foreach}
</tbody>
<tfoot>
<tr>
<td></td>
- <th>Solde final</th>
- <td>{if $souscompte.debit > 0}{$souscompte.debit|html_money}{/if}</td>
- <td>{if $souscompte.credit > 0}{$souscompte.credit|html_money}{/if}</td>
+ <td></td>
+ <td><b>Solde final</b></td>
+ <td>{if $souscompte.debit != 0}{$souscompte.debit|html_money}{/if}</td>
+ <td>{if $souscompte.credit != 0}{$souscompte.credit|html_money}{/if}</td>
</tr>
</tfoot>
</table>
<tfoot>
<tr>
<td>Total</td>
- <th>{$code|get_nom_compte|escape}</th>
+ <td><b><span class="num"><a href="{$admin_url}compta/comptes/journal.php?id={$code|escape}">{$code|escape}</a></span> — {$code|get_nom_compte|escape}</b></td>
<td>{if $compte.total > 0}{$compte.total|abs|html_money}{/if}</td>
<td>{if $compte.total < 0}{$compte.total|abs|html_money}{/if}</td>
</tr>
<p class="help">Toutes les opérations sont libellées en {$config.monnaie|escape}.</p>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
<table class="list multi">
<thead>
<tr>
- <td>Date</td>
+ <th>N°</th>
+ <th>Date</th>
<th>Intitulé</th>
- <td>Comptes</td>
- <td>Débit</td>
- <td>Crédit</td>
+ <th colspan="2">Comptes</th>
+ <th>Débit</th>
+ <th>Crédit</th>
</tr>
</thead>
<tbody>
{foreach from=$journal item="ligne"}
- <tr>
- <td rowspan="2">{$ligne.date|date_fr:'d/m/Y'|escape}</td>
- <th rowspan="2">{$ligne.libelle|escape}</th>
- <td>{$ligne.compte_debit|escape} - {$ligne.compte_debit|get_nom_compte|escape}</td>
+ <tr class='{if $ligne.id % 2 == 0}even{else}odd{/if}'>
+ <td class="num">{if isset($ligne.date)}<a href="{$admin_url}compta/operations/voir.php?id={$ligne.id|escape}">{$ligne.id|escape}</a>{/if}</td>
+ <td>{if isset($ligne.date)}{$ligne.date|date_fr:'d/m/Y'|escape}{/if}</td>
+ <td>{if isset($ligne.date)}{$ligne.libelle|escape}{/if}</td>
+ <td><a href="{$admin_url}compta/comptes/journal.php?id={$ligne.compte|escape}">{$ligne.compte|escape}</a></td>
+ <td>{$ligne.compte|get_nom_compte|escape}</td>
+ {if $ligne.montant > 0}
<td>{$ligne.montant|html_money}</td>
<td></td>
- </tr>
- <tr>
- <td>{$ligne.compte_credit|escape} - {$ligne.compte_credit|get_nom_compte|escape}</td>
+ {else}
<td></td>
- <td>{$ligne.montant|html_money}</td>
+ <td>{$ligne.montant_oppose|html_money}</td>
+ {/if}
</tr>
{/foreach}
</tbody>
<p class="help">Toutes les opérations sont libellées en {$config.monnaie|escape}.</p>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
<dl>
<dt><label for="f_file">Fichier à importer</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
<dd><input type="file" name="upload" id="f_file" required="required" /></dd>
+ <dt><label for="f_file_plan_comptable">Fichier JSON du Plan comptable à importer</label> <b title="(Champ optionnel)">optionnel</b></dt>
+ <dd><input type="file" name="upload-plan-comptable" id="f_file_plan_comptable" /></dd>
<dt><label for="f_type">Type de fichier</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
<dd>
<input type="radio" name="type" id="f_type" value="garradin" {form_field name=type checked="garradin" default="garradin"} />
</form>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
</td>
<td>{$ligne.date|date_fr:'d/m/Y'|escape}</td>
<td>{$ligne.montant|html_money} {$config.monnaie|escape}</td>
- <th>{$ligne.libelle|escape}</th>
+ <td>{$ligne.libelle|escape}</td>
{if !$categorie && $type}
<td>{$ligne.categorie|escape}</td>
{/if}
</tfoot>
</table>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
</p>
{/if}
+{if $debug}
+ <p class="debug">
+ {$debug|escape}
+ </p>
+{/if}
+
<form method="post" action="{$self_url|escape}">
<fieldset>
<dd><input type="date" name="date" id="f_date" value="{form_field name=date default=$operation.date|date_fr:'Y-m-d'}" size="10" required="required" /></dd>
<dt><label for="f_libelle">Libellé</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
<dd><input type="text" name="libelle" id="f_libelle" value="{form_field name=libelle data=$operation}" required="required" /></dd>
- <dt><label for="f_montant">Montant</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd><input type="number" size="5" name="montant" id="f_montant" value="{form_field name=montant data=$operation}" min="0.00" step="0.01" required="required" /> {$config.monnaie|escape}</dd>
{if is_null($type)}
- <dt><label for="f_compte_debit">Compte débité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd>
- {select_compte comptes=$comptes name="compte_debit" data=$operation}
- </dd>
- <dt><label for="f_compte_credit">Compte crédité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd>
- {select_compte comptes=$comptes name="compte_credit" data=$operation}
- </dd>
+ <fieldset id="fluxs">
+ <legend>Flux <b title="(Champ obligatoire)">obligatoire</b></legend>
+ <table>
+ <thead>
+ <tr>
+ <th><label for="f_compte">Compte</label></th>
+ <th><label for="f_montant">Montant<br /><b title="">crédit < 0 < débit</b></label></th>
+ </tr>
+ </thead>
+ <tbody>
+ {foreach from=$fluxs item="flux" key="flux_n" name="fluxs"}
+ <tr>
+ <td class="compte">{select_compte comptes=$comptes name="compte" form_name="compte_$flux_n" id="f_compte_$flux_n" data=$flux}</td>
+ {if !$tpl.foreach.fluxs.last}
+ <td class="montant"><input type="number" size="5" name="montant_{$flux_n}" id="f_montant_{$flux_n}"
+ value="{form_field name="montant" data=$flux}"
+ min="0.00" step="0.01" required="required"
+ /> {$config.monnaie|escape}</td>
+ {/if}
+ </tr>
+ {/foreach}
+ </tbody>
+ </table>
+ </fieldset>
{else}
<dt><label for="f_moyen_paiement">Moyen de paiement</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
<dd>
</dl>
</fieldset>
-{if !is_null($type)}
+{if is_null($type)}
+ <script type="text/javascript">
+ {literal}
+ (function () {
+ if (!document.querySelector || !document.querySelectorAll)
+ {
+ return false;
+ }
+ fluxs = document.querySelector('#fluxs');
+ if (fluxs)
+ {
+ var fluxs = fluxs.querySelectorAll('#fluxs > table > tbody > tr');
+ var fluxs_nb = fluxs.length;
+
+ var add = document.createElement('input');
+ add.type = 'button';
+ add.className = 'icn add';
+ add.value = '+';
+ add.title = 'Ajouter un flux';
+ add.onclick = function (e) {
+ var p = this.parentNode.parentNode; // tbody
+ var fluxs = p.querySelectorAll('tr'); // tr
+ var fluxs_nb = fluxs.length;
+
+ // Add new last flux
+ var new_flux = this.parentNode.cloneNode(true); // tr
+ var new_compte = new_flux.querySelector('.compte');
+ new_compte.querySelector('select').id = 'f_compte_'+fluxs_nb;
+ new_compte.querySelector('select').name = 'compte_'+fluxs_nb;
+ p.appendChild(new_flux);
+
+ // Add a montant to old last flux
+ var new_montant = fluxs[0].querySelector('.montant').cloneNode(true);
+ new_montant.querySelector('input').id = 'f_montant_'+(fluxs_nb - 1);
+ new_montant.querySelector('input').name = 'montant_'+(fluxs_nb - 1);
+ new_montant.querySelector('input').value = '0';
+ this.parentNode.appendChild(new_montant);
+ this.parentNode.removeChild(this);
+
+ // Register this callback on new flux
+ var btn = new_flux.querySelector('input.add');
+ btn.onclick = this.onclick;
+ };
+
+ fluxs[fluxs_nb - 1].appendChild(add);
+ }
+ }());
+ {/literal}
+ </script>
+{else}
<fieldset>
<legend>Catégorie</legend>
<dl class="catList">
</form>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
</p>
{/if}
+{if $debug}
+ <p class="debug">
+ {$debug|escape}
+ </p>
+{/if}
+
{if $ok}
<p class="confirm">
L'opération numéro <a href="{$www_url}admin/compta/operations/voir.php?id={$ok|escape}">{$ok|escape}</a> a été ajoutée.
<dd><input type="date" name="date" id="f_date" value="{form_field name=date default=$date}" size="10" required="required" /></dd>
<dt><label for="f_libelle">Libellé</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
<dd><input type="text" name="libelle" id="f_libelle" value="{form_field name=libelle}" required="required" /></dd>
- <dt><label for="f_montant">Montant</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd><input type="number" size="5" name="montant" id="f_montant" value="{form_field name=montant default=0.00}" min="0.00" step="0.01" required="required" /> {$config.monnaie|escape}</dd>
{if is_null($type)}
- <dt><label for="f_compte_debit">Compte débité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd>
- {select_compte comptes=$comptes name="compte_debit"}
- </dd>
- <dt><label for="f_compte_credit">Compte crédité</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
- <dd>
- {select_compte comptes=$comptes name="compte_credit"}
- </dd>
+ <fieldset id="fluxs">
+ <legend>Flux <b title="(Champ obligatoire)">obligatoire</b></legend>
+ <table>
+ <thead>
+ <tr>
+ <th><label for="f_compte">Compte</label></th>
+ <th><label for="f_montant">Montant<br /><b title="">crédit < 0 < débit</b></label></th>
+ </tr>
+ </thead>
+ <tbody>
+ {foreach from=$fluxs item="flux" key="flux_n" name="fluxs"}
+ <tr>
+ <td class="compte">{select_compte comptes=$comptes name="compte" form_name="compte_$flux_n" id="f_compte_$flux_n" data=$flux}</td>
+ {if !$tpl.foreach.fluxs.last}
+ <td class="montant"><input type="number" size="5" name="montant_{$flux_n}" id="f_montant_{$flux_n}"
+ value="{form_field name="montant" data=$flux}"
+ min="0.00" step="0.01" required="required"
+ /> {$config.monnaie|escape}</td>
+ {/if}
+ </tr>
+ {/foreach}
+ </tbody>
+ </table>
+ </fieldset>
{elseif $type === 'virement'}
<dt><label for="f_compte1">Compte débité</label></dt>
<dd>
</dl>
</fieldset>
-{if $type == Garradin\Compta_Categories::DEPENSES || $type == Garradin\Compta_Categories::RECETTES || $type == 'dette'}
+{if is_null($type)}
+ <script type="text/javascript">
+ {literal}
+ (function () {
+ if (!document.querySelector || !document.querySelectorAll)
+ {
+ return false;
+ }
+ fluxs = document.querySelector('#fluxs');
+ if (fluxs)
+ {
+ var fluxs = fluxs.querySelectorAll('#fluxs > table > tbody > tr');
+ var fluxs_nb = fluxs.length;
+
+ var add = document.createElement('input');
+ add.type = 'button';
+ add.className = 'icn add';
+ add.value = '+';
+ add.title = 'Ajouter un flux';
+ add.onclick = function (e) {
+ var p = this.parentNode.parentNode; // tbody
+ var fluxs = p.querySelectorAll('tr'); // tr
+ var fluxs_nb = fluxs.length;
+
+ // Add new last flux
+ var new_flux = this.parentNode.cloneNode(true); // tr
+ var new_compte = new_flux.querySelector('.compte');
+ new_compte.querySelector('select').id = 'f_compte_'+fluxs_nb;
+ new_compte.querySelector('select').name = 'compte_'+fluxs_nb;
+ p.appendChild(new_flux);
+
+ // Add a montant to old last flux
+ var new_montant = fluxs[0].querySelector('.montant').cloneNode(true);
+ new_montant.querySelector('input').id = 'f_montant_'+(fluxs_nb - 1);
+ new_montant.querySelector('input').name = 'montant_'+(fluxs_nb - 1);
+ new_montant.querySelector('input').value = '0';
+ this.parentNode.appendChild(new_montant);
+ this.parentNode.removeChild(this);
+
+ // Register this callback on new flux
+ var btn = new_flux.querySelector('input.add');
+ btn.onclick = this.onclick;
+ };
+
+ fluxs[fluxs_nb - 1].appendChild(add);
+ }
+ }());
+ {/literal}
+ </script>
+{elseif $type == Garradin\Compta_Categories::DEPENSES || $type == Garradin\Compta_Categories::RECETTES || $type == 'dette'}
<fieldset>
<legend>Catégorie</legend>
<dl class="catList">
</form>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
<dd>{$operation.date|date_fr:'l j F Y (d/m/Y)'}</dd>
<dt>Libellé</dt>
<dd>{$operation.libelle|escape}</dd>
- <dt>Montant</dt>
- <dd>{$operation.montant|html_money} {$config.monnaie|escape}</dd>
<dt>Numéro pièce comptable</dt>
<dd>{if trim($operation.numero_piece)}{$operation.numero_piece|escape}{else}<em>Non renseigné</em>{/if}</dd>
<dd>{if trim($operation.remarques)}{$operation.remarques|escape}{else}Non renseigné{/if}</dd>
</dl>
-<table class="list multi">
+<table class="list multi table">
<thead>
<tr>
<th colspan="2">Comptes</th>
- <td>Débit</td>
- <td>Crédit</td>
+ <th>Débit</th>
+ <th>Crédit</th>
</tr>
</thead>
<tbody>
+ {foreach from=$fluxs item="flux"}
<tr>
- <td><a href="{$admin_url}compta/comptes/journal.php?id={$operation.compte_debit|escape}">{$operation.compte_debit|escape}</a></td>
- <td>{$nom_compte_debit}</td>
- <td>{$operation.montant|html_money} {$config.monnaie|escape}</td>
+ <td><a href="{$admin_url}compta/comptes/journal.php?id={$flux.compte|escape}">{$flux.compte|escape}</a></td>
+ <td>{$flux.compte_libelle}</td>
+ {if $flux.montant > 0}
+ <td>{$flux.montant|html_money} {$config.monnaie|escape}</td>
<td></td>
- </tr>
- <tr>
- <td><a href="{$admin_url}compta/comptes/journal.php?id={$operation.compte_credit|escape}">{$operation.compte_credit|escape}</a></td>
- <td>{$nom_compte_credit}</td>
+ {else}
<td></td>
- <td>{$operation.montant|html_money} {$config.monnaie|escape}</td>
+ <td>{$flux.montant_oppose|html_money} {$config.monnaie|escape}</td>
+ {/if}
</tr>
+ {/foreach}
</tbody>
</table>
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
{/if}
{/if}
+{if $debug}
+ <p class="debug">
+ TOTO
+ {$debug|escape}
+ </p>
+{/if}
+
+
{if $review}
<fieldset>
<legend>Fiche membre exemple</legend>
</script>
{/if}
-{include file="admin/_foot.tpl"}
\ No newline at end of file
+{include file="admin/_foot.tpl"}
$solde = $journal->getSolde($compte['id']);
-if (($compte['position'] & Compta_Comptes::ACTIF) || ($compte['position'] & Compta_Comptes::CHARGE))
-{
- $tpl->assign('credit', '-');
- $tpl->assign('debit', '+');
-}
-else
-{
- $tpl->assign('credit', '+');
- $tpl->assign('debit', '-');
-}
-
$tpl->assign('compte', $compte);
$tpl->assign('solde', $solde);
$tpl->assign('journal', $journal->getJournalCompte($compte['id']));
$tpl->display('admin/compta/comptes/journal.tpl');
-?>
\ No newline at end of file
+?>
}
$tpl->register_modifier('get_nom_compte', 'Garradin\get_nom_compte');
+
$tpl->assign('compte_resultat', $exercices->getCompteResultat($exercice['id']));
$tpl->assign('cloture', $exercice['cloture'] ? $exercice['fin'] : time());
$tpl->display('admin/compta/exercices/compte_resultat.tpl');
-?>
\ No newline at end of file
+?>
}
$tpl->register_modifier('get_nom_compte', 'Garradin\get_nom_compte');
-$tpl->assign('journal', $exercices->getJournal($exercice['id']));
+$journal = $exercices->getJournal($exercice['id']);
+$id = -1;
+foreach ($journal as &$ligne)
+{
+ if ($ligne['id'] == $id)
+ {
+ unset($ligne['date']);
+ unset($ligne['libelle']);
+ }
+ else
+ {
+ $id = $ligne['id'];
+ }
+}
+$tpl->assign('journal', $journal);
$tpl->assign('cloture', $exercice['cloture'] ? $exercice['fin'] : time());
$tpl->assign('exercice', $exercice);
$tpl->display('admin/compta/exercices/journal.tpl');
-?>
\ No newline at end of file
+?>
$e = new Compta_Exercices;
$import = new Compta_Import;
+$comptes = new Compta_Comptes;
if (isset($_GET['export']))
{
{
$error = 'Une erreur est survenue, merci de renvoyer le formulaire.';
}
- elseif (empty($_FILES['upload']['tmp_name']))
+ if (empty($_FILES['upload']['tmp_name']))
{
$error = 'Aucun fichier fourni.';
}
{
try
{
+ if (isset($_FILES['upload-plan-comptable']))
+ {
+ if (!$comptes->importPlan($_FILES['upload-plan-comptable']['tmp_name']))
+ {
+ throw new UserException('Erreur lors de l’import du plan comptable');
+ }
+ }
if (utils::post('type') == 'citizen')
{
$import->fromCitizen($_FILES['upload']['tmp_name']);
}
elseif (utils::post('type') == 'garradin')
{
- $import->fromCSV($_FILES['upload']['tmp_name']);
+ if (!$import->fromCSV($_FILES['upload']['tmp_name']))
+ {
+ throw new UserException('Erreur lors de l’import');
+ }
}
else
{
$tpl->display('admin/compta/import.tpl');
-?>
\ No newline at end of file
+?>
$list = $journal->getListForCategory($type === Compta_Categories::AUTRES ? null : $type, $cat ? $cat['id'] : null);
$tpl->assign('categorie', $cat);
-$tpl->assign('journal', $list);
$tpl->assign('type', $type);
if ($type !== Compta_Categories::AUTRES)
}
$total = 0.0;
-
-foreach ($list as $row)
+foreach ($list as &$row)
{
- $total += (float) $row['montant'];
+ $db = DB::getInstance();
+ $row['montant'] =
+ $db->simpleQuerySingle('
+ SELECT sum(CASE WHEN montant > 0 THEN montant ELSE 0 END)
+ FROM compta_flux
+ WHERE compta_flux.id_journal = ?', false, $row['id']);
+ $total += round((float) $row['montant'], 2);
}
-
+$tpl->assign('journal', $list);
$tpl->assign('total', $total);
$tpl->display('admin/compta/operations/index.tpl');
-?>
\ No newline at end of file
+?>
$tpl->display('admin/compta/operations/membre.tpl');
-?>
\ No newline at end of file
+?>
throw new UserException("L'opération demandée n'existe pas.");
}
+$debug = "_POST=".print_r($_POST, true);
+
if ($operation['id_categorie'])
{
$categorie = $cats->get($operation['id_categorie']);
$type = null;
}
+foreach ($operation['fluxs'] as $key => &$flux)
+{
+ $compte = $comptes->get($flux['compte']);
+ $flux['compte_libelle'] = $compte['libelle'];
+}
+$tpl->assign('fluxs', $operation['fluxs']);
+
$error = false;
if (!empty($_POST['save']))
{
if (is_null($type))
{
+ $fluxs = [];
+ $solde = 0.0;
+ for ($n=0; array_key_exists('compte_'.$n, $_POST); $n++)
+ {
+ $compte = $_POST['compte_'.$n];
+ if (array_key_exists('montant_'.$n, $_POST)) {
+ $montant = $_POST['montant_'.$n];
+ if ($montant == 0.0)
+ {
+ continue;
+ }
+ else
+ {
+ $solde += $montant;
+ $fluxs[] = ['compte' => $compte, 'montant' => $montant];
+ }
+ } else {
+ if ($solde != 0.0 || $n < 1) {
+ $fluxs[] = ['compte' => $compte, 'montant' => - $solde];
+ }
+ break;
+ }
+ }
$journal->edit($operation['id'], [
'libelle' => utils::post('libelle'),
- 'montant' => utils::post('montant'),
+ 'fluxs' => $fluxs,
'date' => utils::post('date'),
- 'compte_credit' => utils::post('compte_credit'),
- 'compte_debit' => utils::post('compte_debit'),
'numero_piece' => utils::post('numero_piece'),
'remarques' => utils::post('remarques'),
]);
$journal->edit($operation['id'], [
'libelle' => utils::post('libelle'),
- 'montant' => utils::post('montant'),
'date' => utils::post('date'),
+ 'fluxs' =>
+ [ ['compte'=>$credit, 'montant' => - utils::post('montant')]
+ , ['compte'=>$debit, 'montant' => utils::post('montant')] ],
'moyen_paiement'=> utils::post('moyen_paiement'),
'numero_cheque' => utils::post('numero_cheque'),
- 'compte_credit' => $credit,
- 'compte_debit' => $debit,
'numero_piece' => utils::post('numero_piece'),
'remarques' => utils::post('remarques'),
'id_categorie' => (int)$cat['id'],
$tpl->assign('comptes_bancaires', $banques->getList());
}
+$tpl->assign('debug', $debug);
$tpl->assign('operation', $operation);
$tpl->display('admin/compta/operations/modifier.tpl');
-?>
\ No newline at end of file
+?>
$type = Compta_Categories::RECETTES;
$error = false;
+$debug = "_POST=".print_r($_POST, true);
if (!empty($_POST['save']))
{
{
if (is_null($type))
{
+ $fluxs = [];
+ $solde = 0.0;
+ for ($n=0; array_key_exists('compte_'.$n, $_POST); $n++)
+ {
+ $compte = $_POST['compte_'.$n];
+ if (array_key_exists('montant_'.$n, $_POST)) {
+ $montant = $_POST['montant_'.$n];
+ if ($montant == 0.0)
+ {
+ continue;
+ }
+ else
+ {
+ $solde += $montant;
+ $fluxs[] = ['compte' => $compte, 'montant' => $montant];
+ }
+ } else {
+ if ($solde != 0.0) {
+ $fluxs[] = ['compte' => $compte, 'montant' => - $solde];
+ }
+ break;
+ }
+ }
+ $debug .= "<br/>fluxs = ".print_r($fluxs, true);
$id = $journal->add([
'libelle' => utils::post('libelle'),
- 'montant' => utils::post('montant'),
'date' => utils::post('date'),
- 'compte_credit' => utils::post('compte_credit'),
- 'compte_debit' => utils::post('compte_debit'),
+ 'fluxs' => $fluxs,
'numero_piece' => utils::post('numero_piece'),
'remarques' => utils::post('remarques'),
'id_auteur' => $user['id'],
{
$id = $journal->add([
'libelle' => utils::post('libelle'),
- 'montant' => utils::post('montant'),
'date' => utils::post('date'),
- 'compte_credit' => utils::post('compte1'),
- 'compte_debit' => utils::post('compte2'),
+ 'fluxs' =>
+ [ ['compte'=>utils::post('compte1'), 'montant' => - utils::post('montant')]
+ , ['compte'=>utils::post('compte2'), 'montant' => utils::post('montant')] ],
'numero_piece' => utils::post('numero_piece'),
'remarques' => utils::post('remarques'),
'id_auteur' => $user['id'],
$id = $journal->add([
'libelle' => utils::post('libelle'),
- 'montant' => utils::post('montant'),
'date' => utils::post('date'),
+ 'fluxs' =>
+ [ ['compte'=>$credit, 'montant' => - utils::post('montant')]
+ , ['compte'=>$debit, 'montant' => utils::post('montant')] ],
'moyen_paiement'=> ($type === 'dette') ? null : utils::post('moyen_paiement'),
'numero_cheque' => ($type === 'dette') ? null : utils::post('numero_cheque'),
- 'compte_credit' => $credit,
- 'compte_debit' => $debit,
'numero_piece' => utils::post('numero_piece'),
'remarques' => utils::post('remarques'),
'id_categorie' => ($type === 'dette') ? null : (int)$cat['id'],
}
$tpl->assign('error', $error);
-
+$tpl->assign('debug', $debug."END");
$tpl->assign('type', $type);
-if ($type === null)
+if (is_null($type))
{
$tpl->assign('comptes', $comptes->listTree());
+ $tpl->assign('fluxs',
+ [ 0 => ['compte' => '', 'montant' => 0.0]
+ , 1 => ['compte' => '', 'montant' => 0.0]
+ ]
+ );
}
else
{
$tpl->display('admin/compta/operations/saisir.tpl');
-?>
\ No newline at end of file
+?>
$tpl->assign('operation', $operation);
-$credit = $comptes->get($operation['compte_credit']);
-$tpl->assign('nom_compte_credit', $credit['libelle']);
-
-$debit = $comptes->get($operation['compte_debit']);
-$tpl->assign('nom_compte_debit', $debit['libelle']);
+foreach ($operation['fluxs'] as $key => &$flux)
+{
+ $compte = $comptes->get($flux['compte']);
+ $flux['compte_libelle'] = $compte['libelle'];
+ $flux['montant_oppose'] = - $flux['montant'];
+}
+$tpl->assign('fluxs', $operation['fluxs']);
$tpl->assign('exercice', $exercices->get($operation['id_exercice']));
$tpl->display('admin/compta/operations/voir.tpl');
-?>
\ No newline at end of file
+?>
$error = 'OK';
}
+$debug = "_POST=".print_r($_POST, true);
+
if (!empty($_POST['save']) || !empty($_POST['add']) || !empty($_POST['review']) || !empty($_POST['reset']))
{
if (!utils::CSRF_check('config_membres'))
}
$tpl->assign('error', $error);
+$tpl->assign('debug', $debug);
$tpl->assign('review', isset($_GET['review']) ? true : false);
$types = $champs->getTypes();
$tpl->display('admin/config/membres.tpl');
-?>
\ No newline at end of file
+?>
font-weight: bold;
}
-fieldset dl dt b {
+fieldset dl dt b,
+fieldset table th b,
+fieldset legend b {
color: #900;
font-size: 0.7em;
font-weight: normal;
background: inherit;
}
-table.list.multi tr:nth-child(4n+1), table.list.multi tr:nth-child(4n+2) {
+table.list.multi tr.odd {
background: rgb(255, 174, 80);
background: rgba(217, 134, 40, 0.2);
}
width: auto !important;
}
+ table.list.table td, table.list.table th {
+ display: table-cell !important;
+ }
+
colgroup {
/* Hack pour désactiver les largeurs de colonnes */
display: none;
float: none;
width: auto;
}
-}
\ No newline at end of file
+}